package com.lagou.edu.context;

import com.lagou.edu.factory.DefaultProxyFactory;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.utils.Assert;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 默认实现的 bean 工厂
 *
 * @author bwcx_jzy
 * @since 2021/10/21
 */
public class DefaultBeanFactory implements BeanFactory {

    /**
     * 全局配置
     */
    private final Properties properties = new Properties();
    /**
     * bean 缓存池
     */
    private final Map<String, BeanData> beanCache = new ConcurrentHashMap<>();
    /**
     * class 对应到 bean name
     */
    private final Map<Class<?>, String> beanClassName = new ConcurrentHashMap<>();

    /**
     * 动态代理工厂
     */
    private final ProxyFactory proxyFactory = new DefaultProxyFactory();

    @Override
    public Object getObject(String name) {
        return beanCache.get(name).getProxyObject();
    }

    @Override
    public <T> T getObject(Class<T> tClass) {
        String s = beanClassName.get(tClass);
        Assert.hasLength(s, "没有找对对应的 bean:" + tClass);
        return (T) this.getObject(s);
    }

    public Object getOriginalObject(String name) {
        return beanCache.get(name).getObject();
    }

    public <T> T getOriginalObject(Class<T> tClass) {
        String s = beanClassName.get(tClass);
        Assert.hasLength(s, "没有找对对应的 bean:" + tClass);
        return (T) this.getOriginalObject(s);
    }

    @Override
    public String getProperties(String name) {
        return properties.getProperty(name);
    }

    /**
     * 注册 bean 到工厂
     *
     * @param name     bean name
     * @param cls      class
     * @param beanData 对象
     */
    public void regBean(String name, Class<?> cls, BeanData beanData) {
        beanCache.put(name, beanData);
        beanClassName.put(cls, name);
    }

    /**
     * 关联 class  beanName 到工厂
     *
     * @param name bean name
     * @param cls  class
     */
    public void regClassBeanName(String name, Class<?> cls) {
        boolean containsKey = beanCache.containsKey(name);
        if (!containsKey) {
            throw new IllegalArgumentException("还没有注册对应的 bean:" + name);
        }
        beanClassName.put(cls, name);
    }

    /**
     * 移除 bean
     *
     * @param name bean 名称
     * @param cls  class
     */
    public void removeBean(String name, Class<?> cls) {
        beanCache.remove(name);
        beanClassName.remove(cls);
    }

    /**
     * 加载配置到全局
     *
     * @param inputStream 配置文件流
     * @throws IOException IO 异常
     */
    public void loadProperties(InputStream inputStream) throws IOException {
        properties.load(inputStream);
    }

    /**
     * 获取当前的 代理工厂
     *
     * @return ProxyFactory
     */
    public ProxyFactory getProxyFactory() {
        return proxyFactory;
    }
}
